#ifndef _WINDOW_H_
#define _WINDOW_H_

#include <interfacelib/frame/userMessage.h>
#include <interfacelib/directx/texture.h>
#include <interfacelib/directx/textureManager.h>
#include <interfacelib/window/fontmanager.h>
#include <interfacelib/window/box.h>
#include <interfacelib/ime/ime.h>
#include <D3D9.h>
#include <d3dx9core.h>
#include <utillib/memory/memory.h>
#pragma warning ( disable: 4786 )
#include <deque>
#include <functional>
#include <InterfaceLib/frame/HandleManager.h>

#define		CLOSE_MODAL_DIALOG( __param, __dailog )			POSTMESSAGE( WM_MODALDIALOG_CLOSE , ( WPARAM )__param, ( LPARAM )__dailog );
#define		MAX_CONTROL_TYPE								interfacelib::Window::Window::CUSTOM + 1
#define		IS_LBUTTON_DOWN( msg )							( ( ( msg->wParam & MK_LBUTTON ) == MK_LBUTTON ) ? true : false )
#define		DRAWTEXT_FORMATTYPE_LENGTH						1024

namespace interfacelib
{
	namespace Window
	{
#define IME_LIMIT_LENGTH		8

#define MOVING_TIME				30
#define	DOUBLE_CLICK_TIME		300
		class Panel;
		class BaloonBox;
		class ImageMenu;
		class Window 
		{
		public:
		enum WindowType
		{
			BALOONBOX = 0,
			BUTTON,
			CAPTION,
			CHECKBUTTON,
			EDITBOX,
			TIMEGAGE,
			STEPGAGE,
			IMAGEMENU,
			MENU,
			MESSAGEBOX,
			PANEL,
			SCROLL,
			SCROLLWITHSTRING,
			SCROLLBUTTON,
			STATICBOX,
			TEXT,
			WINDOW,
			BUFF,
			CUSTOM,
			INVALID,
		};
		enum WindowStyle
		{
			VISIBLE = 0x01,
			MOVABLE = 0x02,
			DISABLEINPUT = 0x04,
			SETINPUTFOCUS = 0x08,
			RESIZE = 0x10,
		};
		
		enum StrokeStyle
		{
			STROKE_UP    = 0x01,
			STROKE_DOWN  = 0x02,
			STROKE_LEFT  = 0x04,
			STROKE_RIGHT = 0x08,
			STROKE_ALL	 = 0x0F,
		};

		public:
		struct TextStyle
		{
			DWORD foreGroundColor;
			DWORD format;
			BYTE strokeMode;
//			bool strokeMode;
			DWORD strokeColor;
		};

		public:
			Window();
			virtual ~Window();

			virtual bool create(const char *filename, int x, int y, DWORD attribute = MOVABLE | VISIBLE );
			virtual bool createTooltip( char *image , int marginX, int marginY ){ return ( true ); };

		public:
			void setTooltip( int x, int y, char *tooltip );
			char *getTooltip();
			void setParent( Panel *parent );

			bool isEnableInput() { return ( ( ( m_attribute & DISABLEINPUT ) == DISABLEINPUT ) ? false : true) ; };
			void setEnableInput( bool enableInput );

			bool isSetInputFocus() { return ( ( ( m_attribute & SETINPUTFOCUS ) == SETINPUTFOCUS ) ? true: false ) ; };
			void setSetInputInput( bool visible );

			bool isResize() { return ( ( ( m_attribute & RESIZE ) == RESIZE ) ? true: false ) ; };
			void setResize( bool resize );

			bool isVisible() { return ( ( ( m_attribute & VISIBLE ) == VISIBLE ) ? true : false ) ; };
			virtual void setVisible( bool visible );

			void setWindowAttribute( DWORD attribute ) { m_attribute = attribute; };

			bool isMovable() { return ( ( ( m_attribute & MOVABLE ) == MOVABLE ) ? true : false ) ; };
			void setMovable( bool movable );

		public:
			virtual void setWindowPos( int x , int y , int width = -1, int height = -1 , bool forceMode = false );

			void getWindowPos( POINT *point , bool real = true );
			void getWindowRect( RECT *rect );
			RECT *getWindowRect() { return ( &m_windowRect );};

			virtual DWORD getWidth();
			virtual DWORD getHeight();

			virtual void preTranslateMessage( MSG *msg );
			void setFont( const char *faceName, int size, int weight ){ m_currentFont = FontManager::getInstance()->getFont( faceName, size, weight ) ;};
			FontManager::FontStruct *getFont(){ return ( m_currentFont ); };
		public:
			bool isPointInWindow( LONG x, LONG y );
			interfacelib::Window::Panel *getParentPanel(){ return ( m_parentPanel ); };

			void drawText( int x, int y, const char *string );
			void drawText( RECT *rect, const char *string );
			void drawFormatText( RECT *rect, const char *format, ...  );
			void getTextSize( SIZE *size , const char *string ,int stringLength = -1 , bool enableEmpty = true );

			virtual bool IMEProcess( UINT message, WPARAM wparam, LPARAM lparam ) { return ( false ); };
			
			virtual void onMouseOver( LONG x, LONG y );
			virtual void onMouseOut( LONG x, LONG y );
			
			virtual void draw( Window *window = NULL );

			virtual void setState( DWORD state ){};
			
			virtual	void onLButtonUp( UINT flags, POINT point );
			virtual	void onLButtonDown( UINT flags, POINT point );
			virtual	void onRButtonUp( UINT flags, POINT point );
			virtual	void onRButtonDown( UINT flags, POINT point );
			virtual void onLButtonDblClk( UINT flags, POINT point );
			virtual void onRButtonDblClk( UINT flags, POINT point );
			virtual void onMouseMove( UINT flags, POINT point );
			virtual void onChar( UINT ch, UINT repeatCount );
			virtual void onKeyDown( UINT ch, UINT repeatCount );
			virtual void onUserIMEResultChar( WPARAM wParam, LPARAM lParam );
			virtual void onUserIMECompChar( WPARAM wParam, LPARAM lParam );

			virtual void setAlphaValue( BYTE a ){ m_alphaValue = ( ( a << 24 ) & 0xFF000000 ) | 0x00FFFFFF; };

			virtual BYTE getAlphaValue(){ return ( BYTE )( ( m_alphaValue >> 24 ) & 0x000000FF ); };

			void setTopWindow();
			
			void setStyle( DWORD foreGround, DWORD backGround )
			{
				m_backGroundEnable = true;
				m_fillBackColor.setColor( backGround );
			}
			void setBackGroundColor( DWORD backGround )
			{
				m_backGroundEnable = true;
				m_fillBackColor.setColor( backGround );
			}

			DWORD getForeGroundColor()
			{
				return m_style.foreGroundColor;				
			};
			void setForeGroundColor( DWORD foreGround )
			{
				m_style.foreGroundColor = foreGround;
			};
			void setFormat( DWORD format )
			{
				m_style.format = format;
			};
			
			void setStrokeMode( BYTE style, DWORD color = D3DCOLOR_ARGB( 255, 0, 0, 0 ) )
			{
				m_style.strokeMode = style;
				m_style.strokeColor = color;
			}

			void disableStrokeMode()
			{
				m_style.strokeMode = 0;
			}
			void enableStrokeMode( DWORD color = D3DCOLOR_ARGB( 255, 0, 0, 0 ) )
			{
				m_style.strokeMode = STROKE_ALL;
				m_style.strokeColor = color;
			};
		
			void checkFrame();
			bool setFrame( BYTE frame );
			bool addFrame();

			bool lastMotion();
			bool isLastSprite();

			void setStartPos( int x = 0, int y = 0 );

			bool isFade();
			virtual void buttonNotify( interfacelib::Window::Window *window ){};
			void setDegree( int degree );
		private:
			bool calcFade();
			
		public:
			LPDIRECT3DTEXTURE9 getTexture()
			{
				if ( !m_currentSprite ) return ( NULL );
				if ( ( m_currentSprite->textureColSize == 0 ) && ( m_currentSprite->textureRowSize == 0 ) )
				{
					interfacelib::DirectX::TextureManager::getInstance()->createTexture( m_currentSprite );
				}
				if ( m_currentSprite->texture ) return ( m_currentSprite->texture[ 0 ] );
				return ( NULL );
			}
			DWORD getSpriteCenterX()
			{
				if ( !m_currentSprite ) return ( NULL );
				return ( ( DWORD )m_currentSprite->centerPoint.centerX );
			}
			DWORD getSpriteCenterY()
			{
				if ( !m_currentSprite ) return ( NULL );
				return ( ( DWORD )m_currentSprite->centerPoint.centerY );
			}
			float getSpriteCenterX3D()
			{
				if ( !m_currentSprite ) return ( NULL );
				return ( m_currentSprite->centerPoint.center3DX );
			}
			float getSpriteCenterY3D()
			{
				if ( !m_currentSprite ) return ( NULL );
				return ( m_currentSprite->centerPoint.center3DY );
			}

			DWORD getSpriteWidth()
			{
				if ( m_currentSprite ) return ( m_currentSprite->bmpInfo.biWidth );
				return ( 0 ); 
			};
			DWORD getSpriteHeight()
			{
				if ( m_currentSprite ) return ( m_currentSprite->bmpInfo.biHeight );
				return ( 0 ); 
			};		
			float getSpriteWidth3D()
			{
				if ( m_currentSprite ) return ( m_currentSprite->width3D );
				return ( 0 ); 
			};
			float getSpriteHeight3D()
			{
				if ( m_currentSprite ) return ( m_currentSprite->height3D );
				return ( 0 ); 
			};
			WORD getMaxMotionIndex()
			{
				if ( m_texture ) return ( m_texture->getMaxMotionIndex() );
				return ( 0 );
			}

			virtual void initialize()
			{
				m_lastAnimationTime = 0;
				
				resetAnimation();
			};
			
		protected:	
			DWORD m_alphaValue;
		protected:
			bool m_dragWindow;
		protected:
			bool m_backGroundEnable;
			Box m_fillBackColor;

			TextStyle m_style;
			
			DWORD m_attribute;

			RECT m_windowRect;

			POINT m_pointLButtonDown;

			Panel *m_parentPanel;

			DWORD m_previousMoveTime;

			interfacelib::DirectX::Texture *m_texture;
			FontManager::FontStruct *m_currentFont;
			
			int m_startX;
			int m_startY;

		public:
			bool setMotionIndex( WORD index );
			WORD getMotionIndex()
			{
				if ( m_currentMotionData ) return ( m_currentMotionData->motionIndex );
				return ( 0xFFFF );
			}
			void resetAnimation()
			{
				if ( m_currentMotionData )
				{
					m_currentMotionData->resetLoopCount();
					m_currentSprite = m_currentMotionData->getFirstSprite();
				}
			};
			void setAnimationLoopCount()
			{
				if ( m_currentMotionData )
				{
					m_currentMotionData->setLoopCount();
					m_currentSprite = m_currentMotionData->getFirstSprite();
				}
			};
		protected:
			MotionData *m_currentMotionData;
			SpriteData *m_currentSprite;

			DWORD m_lastAnimationTime;
		protected:
			struct Fade
			{
				bool enable;
				BYTE targetAlpha;
				BYTE startAlpha;
				DWORD time;
				DWORD startFadeTime;
			};

			Fade m_fade;
		public:
			virtual void fade( BYTE startAlpha, BYTE targetAlpha, DWORD time );
			virtual void fade( Fade *fadeInfo );

			void fadeIn( DWORD time , BYTE startAlpha = 0 );
			void fadeOut( DWORD time , BYTE startAlpha = 0xFF );

		protected:
			POINT m_tooltipPosition;
			POINT m_tooltipMargin;
		private:
			typedef std::deque < POINT * > movePoint;
			movePoint m_movePoint;
			char *m_tooltip;
			int m_degree;
			
		public:
			virtual void moveTo( int targetX, int targetY , int speed );
			virtual bool move();
			bool isMove();
			
			void removeAllMovePoint();
			bool getTargetPos( POINT *point );

			virtual bool add( Window *window ){ return ( false ); };

#ifdef		_DEBUG
		public:
			virtual void setDisplayPosition( bool mode );
			bool isDisplayPosition();
		private:
			bool m_displayPosition;
			void drawPosition();
#endif
		protected:
			bool postMessage( unsigned int msgID, WPARAM wparam, LPARAM lparam );

			friend interfacelib::Window::ImageMenu;
			friend interfacelib::Window::BaloonBox;
		};
	}
}

#endif